"""
数据验证工具模块
"""

import re
from datetime import datetime
from typing import Optional, Tuple, List


def validate_task_title(title: str) -> Tuple[bool, str]:
    """
    验证任务标题
    
    Args:
        title: 任务标题
        
    Returns:
        (是否有效, 错误消息)
    """
    if not title:
        return False, "任务标题不能为空"
    
    title = title.strip()
    if not title:
        return False, "任务标题不能为空"
    
    if len(title) > 200:
        return False, "任务标题不能超过200个字符"
    
    # 检查是否包含非法字符
    illegal_chars = ['<', '>', '"', "'", '&']
    for char in illegal_chars:
        if char in title:
            return False, f"任务标题不能包含字符: {char}"
    
    return True, "标题验证通过"


def validate_task_description(description: Optional[str]) -> Tuple[bool, str]:
    """
    验证任务描述
    
    Args:
        description: 任务描述
        
    Returns:
        (是否有效, 错误消息)
    """
    if description is None:
        return True, "描述验证通过"
    
    if len(description) > 1000:
        return False, "任务描述不能超过1000个字符"
    
    return True, "描述验证通过"


def validate_priority(priority: str) -> Tuple[bool, str]:
    """
    验证优先级
    
    Args:
        priority: 优先级
        
    Returns:
        (是否有效, 错误消息)
    """
    valid_priorities = ['high', 'medium', 'low']
    
    if priority not in valid_priorities:
        return False, f"无效的优先级: {priority}。有效选项: {', '.join(valid_priorities)}"
    
    return True, "优先级验证通过"


def validate_status(status: str) -> Tuple[bool, str]:
    """
    验证任务状态
    
    Args:
        status: 任务状态
        
    Returns:
        (是否有效, 错误消息)
    """
    valid_statuses = ['todo', 'in_progress', 'completed']
    
    if status not in valid_statuses:
        return False, f"无效的状态: {status}。有效选项: {', '.join(valid_statuses)}"
    
    return True, "状态验证通过"


def validate_category(category: Optional[str]) -> Tuple[bool, str]:
    """
    验证任务分类
    
    Args:
        category: 任务分类
        
    Returns:
        (是否有效, 错误消息)
    """
    if category is None:
        return True, "分类验证通过"
    
    category = category.strip()
    if len(category) > 50:
        return False, "分类名称不能超过50个字符"
    
    # 检查分类名称格式
    if not re.match(r'^[a-zA-Z0-9\u4e00-\u9fff_-]+$', category):
        return False, "分类名称只能包含字母、数字、中文、下划线和连字符"
    
    return True, "分类验证通过"


def validate_due_date(due_date: Optional[str]) -> Tuple[bool, str]:
    """
    验证截止日期
    
    Args:
        due_date: 截止日期
        
    Returns:
        (是否有效, 错误消息)
    """
    if due_date is None:
        return True, "日期验证通过"
    
    # 支持的日期格式
    date_formats = [
        '%Y-%m-%d',
        '%Y-%m-%d %H:%M:%S',
        '%Y-%m-%dT%H:%M:%S'
    ]
    
    for fmt in date_formats:
        try:
            parsed_date = datetime.strptime(due_date, fmt)
            
            # 检查日期是否合理（不能是过去太久的日期）
            min_date = datetime(2020, 1, 1)
            max_date = datetime(2030, 12, 31)
            
            if parsed_date < min_date:
                return False, "截止日期不能早于2020年"
            
            if parsed_date > max_date:
                return False, "截止日期不能晚于2030年"
            
            return True, "日期验证通过"
            
        except ValueError:
            continue
    
    return False, "日期格式无效，请使用 YYYY-MM-DD 格式"


def validate_task_id(task_id: any) -> Tuple[bool, str]:
    """
    验证任务 ID
    
    Args:
        task_id: 任务 ID
        
    Returns:
        (是否有效, 错误消息)
    """
    try:
        id_int = int(task_id)
        if id_int <= 0:
            return False, "任务 ID 必须是正整数"
        return True, "ID 验证通过"
    except (ValueError, TypeError):
        return False, "任务 ID 必须是有效的整数"


def validate_search_keyword(keyword: str) -> Tuple[bool, str]:
    """
    验证搜索关键词
    
    Args:
        keyword: 搜索关键词
        
    Returns:
        (是否有效, 错误消息)
    """
    if not keyword:
        return False, "搜索关键词不能为空"
    
    keyword = keyword.strip()
    if not keyword:
        return False, "搜索关键词不能为空"
    
    if len(keyword) < 2:
        return False, "搜索关键词至少需要2个字符"
    
    if len(keyword) > 100:
        return False, "搜索关键词不能超过100个字符"
    
    return True, "关键词验证通过"


def validate_export_format(format_name: str) -> Tuple[bool, str]:
    """
    验证导出格式
    
    Args:
        format_name: 格式名称
        
    Returns:
        (是否有效, 错误消息)
    """
    valid_formats = ['json', 'csv']
    
    if format_name.lower() not in valid_formats:
        return False, f"不支持的导出格式: {format_name}。支持的格式: {', '.join(valid_formats)}"
    
    return True, "格式验证通过"


def validate_page_number(page: any, total_pages: int = None) -> Tuple[bool, str]:
    """
    验证页码
    
    Args:
        page: 页码
        total_pages: 总页数
        
    Returns:
        (是否有效, 错误消息)
    """
    try:
        page_int = int(page)
        if page_int <= 0:
            return False, "页码必须是正整数"
        
        if total_pages and page_int > total_pages:
            return False, f"页码不能超过总页数 {total_pages}"
        
        return True, "页码验证通过"
    except (ValueError, TypeError):
        return False, "页码必须是有效的整数"


def validate_batch_ids(ids: List[any]) -> Tuple[bool, str, List[int]]:
    """
    验证批量 ID 列表
    
    Args:
        ids: ID 列表
        
    Returns:
        (是否有效, 错误消息, 有效的 ID 列表)
    """
    if not ids:
        return False, "ID 列表不能为空", []
    
    valid_ids = []
    invalid_ids = []
    
    for id_item in ids:
        try:
            id_int = int(id_item)
            if id_int > 0:
                valid_ids.append(id_int)
            else:
                invalid_ids.append(str(id_item))
        except (ValueError, TypeError):
            invalid_ids.append(str(id_item))
    
    if invalid_ids:
        return False, f"无效的 ID: {', '.join(invalid_ids)}", valid_ids
    
    if not valid_ids:
        return False, "没有有效的 ID", []
    
    return True, "ID 列表验证通过", valid_ids


def validate_sort_field(field: str) -> Tuple[bool, str]:
    """
    验证排序字段
    
    Args:
        field: 排序字段
        
    Returns:
        (是否有效, 错误消息)
    """
    valid_fields = ['id', 'title', 'priority', 'status', 'category', 'due_date', 'created_at', 'updated_at']
    
    if field not in valid_fields:
        return False, f"无效的排序字段: {field}。有效字段: {', '.join(valid_fields)}"
    
    return True, "排序字段验证通过"


def validate_filter_params(filters: dict) -> Tuple[bool, str, dict]:
    """
    验证过滤参数
    
    Args:
        filters: 过滤参数字典
        
    Returns:
        (是否有效, 错误消息, 清理后的过滤参数)
    """
    clean_filters = {}
    errors = []
    
    for key, value in filters.items():
        if key == 'status':
            valid, msg = validate_status(value)
            if valid:
                clean_filters['status'] = value
            else:
                errors.append(f"状态过滤: {msg}")
        
        elif key == 'priority':
            valid, msg = validate_priority(value)
            if valid:
                clean_filters['priority'] = value
            else:
                errors.append(f"优先级过滤: {msg}")
        
        elif key == 'category':
            if value:  # 只有非空值才验证
                valid, msg = validate_category(value)
                if valid:
                    clean_filters['category'] = value
                else:
                    errors.append(f"分类过滤: {msg}")
        
        else:
            errors.append(f"不支持的过滤字段: {key}")
    
    if errors:
        return False, "; ".join(errors), clean_filters
    
    return True, "过滤参数验证通过", clean_filters


def sanitize_input(text: str) -> str:
    """
    清理用户输入，防止注入攻击
    
    Args:
        text: 原始文本
        
    Returns:
        清理后的文本
    """
    if not text:
        return ""
    
    # 移除潜在的危险字符
    dangerous_chars = ['<', '>', '"', "'", '&', ';', '|', '`']
    cleaned = text
    
    for char in dangerous_chars:
        cleaned = cleaned.replace(char, '')
    
    # 限制长度
    if len(cleaned) > 1000:
        cleaned = cleaned[:1000]
    
    return cleaned.strip()